package com.gaogzhen.service.impl;

import com.gaogzhen.constant.LoginConstant;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String loginType = requestAttributes.getRequest().getParameter("login_type");
        if (StringUtils.isBlank(loginType)) {
            throw new AuthenticationServiceException("登录方式不能为空");
        }

        UserDetails userDetails = null;
        try {
            String grantType = requestAttributes.getRequest().getParameter("grant_type");
            if (LoginConstant.REFRESH_TOKEN.equals(grantType)) {
                username = adjustUsername(username, loginType);
            }
            switch (loginType) {
                case LoginConstant.ADMIN_TYPE:
                    userDetails = LoadSysUserByUsername(username);
                    break;
                case LoginConstant.MEMBER_TYPE:
                    userDetails = LoadMemberUserByUsername(username);
                    break;
                default:
                    throw new AuthenticationServiceException("暂不支持的登录方式：" + loginType);
            }
        }catch (IncorrectResultSizeDataAccessException  e) {
            throw new UsernameNotFoundException("用户名" + username + "不存在");
        } catch (AuthenticationServiceException e) {
            throw new AuthenticationServiceException("暂不支持的登录方式：" + loginType);
        }

        return userDetails;
    }

    /**
     * 根据授权是否为refresh_token调整用户ID为用户名
     * @param username      用户名（用户ID）
     * @param loginType     登录类型
     * @return              用户名
     */
    private String adjustUsername(String username, String loginType) {
        if (LoginConstant.ADMIN_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_WITH_ID, String.class, username);
        } else if (LoginConstant.MEMBER_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_WITH_ID, String.class, username);
        } else {
            return username;
        }
    }

    /**
     * 会员登录
     * @param username 用户名
     * @return
     */
    private UserDetails LoadMemberUserByUsername(String username) {
        // 1、根据用户名查询用户
        // 2、根据用户ID查询权限
        // 3、封装用户
        return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                if (rs.wasNull()) {
                    throw new UsernameNotFoundException("用户名" + username + "不存在");
                }
                long id = rs.getLong("id");
                String password =rs.getString("password");
                int status = rs.getInt("status");
                return new User(
                        String.valueOf(id),
                        password,
                        status == 1,
                        true,
                        true,
                        true,
                        Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
                );
            }
        }, username, username);
    }

    /**
     * 后台管理员登录
     * @param username 用户名
     * @return
     */
    private UserDetails LoadSysUserByUsername(String username) {
        // 1、根据用户名查询用户
        // 2、根据用户ID查询权限
        // 3、封装用户
        return jdbcTemplate.queryForObject(LoginConstant.QUERY_AMDIN_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                if (rs.wasNull()) {
                    throw new UsernameNotFoundException("用户名" + username + "不存在");
                }
                // 用户ID
                long id = rs.getLong("id");
                // 用户密码
                String password = rs.getString("password");
                // 用户状态
                int status = rs.getInt("status");
                return new User(
                        String.valueOf(id),
                        password,
                        status == 1,
                        true,
                        true,
                        true,
                        getSysUserPermissions(id)
                );
            }
        }, username);
    }

    /**
     * 根据用户ID获取权限
     * @param id    用户ID
     * @return
     */
    private Collection<? extends GrantedAuthority> getSysUserPermissions(long id) {
        // 1、根据用户ID获取角色
        String roleCode = jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL, String.class, id);
        // 2、判断用户是否为管理员
        if (StringUtils.isBlank(roleCode)) {
            throw new AuthenticationServiceException("用户未分配角色");
        }
        List<String> permissions = null;
        if (StringUtils.equals(LoginConstant.ADMIN_ROLE_CODE, roleCode)) {
            // 2.1、管理员有全部的权限
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS, String.class);
        } else {
            // 2.2、会员根据用户ID查询权限
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL, String.class, id);
        }
        if (CollectionUtils.isEmpty(permissions)) {
            return null;
        }
        return permissions.stream()
                .distinct()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toSet());

    }
}
